package com.tengju.data.infrastructure.repository;

import com.google.common.collect.Lists;
import com.tengju.data.domain.model.analysis.Row;
import com.tengju.data.domain.model.exchvesion.DataName;
import com.tengju.data.domain.model.exchvesion.SyncStatus;
import com.tengju.data.domain.model.report.*;
import com.tengju.data.domain.model.user.UserIdCode;
import com.tengju.data.domain.shared.Year;
import com.tengju.data.infrastructure.persistence.mybatis.dataobject.AchievementBonusDO;
import com.tengju.data.infrastructure.persistence.mybatis.dataobject.AchievementBonusSumDO;
import com.tengju.data.infrastructure.persistence.mybatis.dataobject.DataExchVersionDO;
import com.tengju.data.infrastructure.persistence.mybatis.dataobject.UserBonusResultDO;
import com.tengju.data.infrastructure.persistence.mybatis.mapper.data.custom.DataExchVersionMapper;
import com.tengju.data.infrastructure.persistence.mybatis.mapper.tengju.custom.AchievementBonusDOCustomMapper;
import com.tengju.data.infrastructure.persistence.mybatis.mapper.tengju.custom.AchievementBonusTempCustomMapper;
import com.tengju.data.infrastructure.repository.convert.AchievementBonusConvert;
import com.tengju.data.infrastructure.shared.BonusException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Repository
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
@Slf4j
public class AchievementBonusRepositoryImpl implements AchievementBonusRepository {

    private final AchievementBonusDOCustomMapper achievementBonusDOCustomMapper;
    private final AchievementBonusTempCustomMapper achievementBonusTempCustomMapper;
    private final DataExchVersionMapper dataExchVersionMapper;

    @Value("${bonus.result.temp}")
    private Boolean insertTemp;

    private static final Integer INSERT_BATCH_LIMIT = 200;

//    @Override
//    public void saveMarketProfitMidInfoRealtime(Integer month, LocalDateTime logTime) {
//        achievementBonusCalMidInfoDOCustomMapper.saveMidInfoRealtime(month,logTime,AchievementBonusCalTypeEnum.REALTIME.getType());
//    }
//
//    @Override
//    public void saveMarketProfitMidInfoMonthSnapshot(LocalDateTime logTime, Integer month) {
//        achievementBonusCalMidInfoDOCustomMapper.saveMidInfoMonth(month,logTime,AchievementBonusCalTypeEnum.MONTH.getType());
//    }
//
//    @Override
//    public void saveMarketProfitMidInfoMonthRisk(LocalDateTime logTime, Integer month) {
//        achievementBonusCalMidInfoDOCustomMapper.saveMidInfoRisk(month,logTime,AchievementBonusCalTypeEnum.MONTH_RISK.getType());
//    }

    @Override
    public void saveAchievementBonus(List<AchievementBonus> allAchievementBonusList) {
        if (CollectionUtils.isEmpty(allAchievementBonusList)) {
            return;
        }
        List<List<AchievementBonus>> partition = Lists.partition(allAchievementBonusList, INSERT_BATCH_LIMIT);
        for (List<AchievementBonus> achievementBonusList : partition) {
            List<AchievementBonusDO> achievementBonusDOList = achievementBonusList.stream()
                    .map(AchievementBonusConvert::convertAchievementBonusToDO)
                    .collect(Collectors.toList());

            //写入临时表
            if (Boolean.TRUE.equals(insertTemp)) {
                log.info("临时对照，写入临时表");
                achievementBonusTempCustomMapper.batchReplaceInsert(achievementBonusDOList);
                continue;
            }

            //正常写入
            achievementBonusDOCustomMapper.batchReplaceInsert(achievementBonusDOList);

        }
    }

    @Override
    @Transactional
    public void saveAchievementBonusLog(LocalDateTime logTime, Integer month) {
        if (Boolean.TRUE.equals(insertTemp)) {
            log.info("临时对照，不写入日志记录表");
            return;
        }
        achievementBonusDOCustomMapper.saveAchievementBonusLog(month, logTime);
        //保存同步状态
        DataExchVersionDO dataExchVersionDO = new DataExchVersionDO();
        dataExchVersionDO.setDataName(DataName.ACHIEVEMENT_BONUS_LOG.getCode());
        dataExchVersionDO.setQueryValue(logTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        dataExchVersionDO.setVersion((int)(logTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()/1000));
        dataExchVersionDO.setStatus(SyncStatus.SYNC_READY.getCode());
        dataExchVersionDO.setCreateTime(LocalDateTime.now());
        dataExchVersionDO.setUpdateTime(LocalDateTime.now());
        dataExchVersionMapper.save(dataExchVersionDO);
    }


//    @Override
//    public List<LocalDateTime> listLogtimeBeforeClearDate(LocalDateTime clearDate) {
//        return achievementBonusCalMidInfoDOCustomMapper.listLogtimeBeforeClearDate(clearDate);
//    }
//
//    @Override
//    public void clearHistoryRecord(LocalDateTime logTime) {
//        achievementBonusCalMidInfoDOCustomMapper.clearHistoryRecord(logTime);
//    }

    @Override
    public List<AchievementBonus> find(LocalDate month, UserIdCode idCode) {
        List<AchievementBonusDO> achievementBonusDOList = achievementBonusDOCustomMapper.queryByMonth(idCode.getValue(), month.getYear() * 100 + month.getMonthValue());
        return achievementBonusDOList.stream().map(AchievementBonusConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public List<AchievementBonus> findByConfigDateKey(Integer dateKey, UserIdCode idCode) {
        if (idCode == null) {
            return Lists.newArrayList();
        }
        List<AchievementBonusDO> achievementBonusDOList = achievementBonusDOCustomMapper.queryByMonth(idCode.getValue(),dateKey);
        return achievementBonusDOList.stream()
                .filter(Objects::nonNull)
                .map(AchievementBonusConvert::convertToModel)
                .collect(Collectors.toList());
    }

    @Override
    public int getMaxVersion() {
        if (Boolean.TRUE.equals(insertTemp)) {
            log.info("临时对照，获取版本");
            return achievementBonusTempCustomMapper.getMaxVersion();
        }
        return achievementBonusDOCustomMapper.getMaxVersion();
    }

    @Override
    public void deleteInvalidData(Integer month, Integer version) {
        if (Boolean.TRUE.equals(insertTemp)) {
            log.info("临时对照，删除无效数据");
            achievementBonusTempCustomMapper.deleteInvalidData(month, version);
            return;
        }
        achievementBonusDOCustomMapper.deleteInvalidData(month, version);
    }

    @Override
    public List<AchievementBonusSum> sumByYear(UserIdCode idCode, LocalDate year) {
        List<AchievementBonusSumDO> achievementBonusDOList = achievementBonusDOCustomMapper.sumByYear(idCode.getValue(),
                year.getYear() * 100, (year.getYear() + 1) * 100);
        return achievementBonusDOList.stream().map(AchievementBonusConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public List<AchievementBonusSum> getAchievementByYear(UserIdCode idCode, Year year) {
        if (idCode == null) {
            return Lists.newArrayList();
        }
        List<AchievementBonusSumDO> achievementBonusSumDOList =
                achievementBonusDOCustomMapper.getAchievementByYear(idCode.getValue(),
                        year.getYearStartMonthInt(),
                        year.getYearEndMonthInt());
        if (CollectionUtils.isEmpty(achievementBonusSumDOList)) {
            return Lists.newArrayList();
        }
        return achievementBonusSumDOList.stream()
                .map(AchievementBonusConvert::convertToModel)
                .collect(Collectors.toList());
    }

    @Override
    public List<Row> getAchievementByTeamRatioType(UserIdCode idCode, Integer month) {
        if (idCode == null) {
            return Lists.newArrayList();
        }
        List<Map<String,Object>> mapList =
                achievementBonusDOCustomMapper.getAchievementByTeamRatioType(idCode.getValue(),month);
        if (CollectionUtils.isEmpty(mapList)) {
            return Lists.newArrayList();
        }
        return mapList.stream()
                .filter(Objects::nonNull)
                .map(Row::new)
                .collect(Collectors.toList());
    }

    @Override
    public List<AchievementBonus> findChild(LocalDate monthDate, UserIdCode idCode) {
        List<AchievementBonusDO> achievementBonusDOList = achievementBonusDOCustomMapper.queryChildByMonth(idCode.getValue(), monthDate.getYear() * 100 + monthDate.getMonthValue());
        return achievementBonusDOList.stream().map(AchievementBonusConvert::convertToModel).collect(Collectors.toList());
    }

    @Override
    public BigDecimal getBonus(@NotNull Long idCode, Integer status, Integer month) {
        if (idCode == null) {
            throw new BonusException("idCode不能为空");
        }
        BigDecimal bonus = achievementBonusDOCustomMapper.getBonus(idCode, status, month);
        return bonus == null ? BigDecimal.ZERO : bonus;
    }

    @Override
    public int countMarketBonusUser(Integer month) {
        return achievementBonusDOCustomMapper.countMarketBonusUser(month);
    }

    @Override
    public List<UserBonusResult> listMarketBonus(Integer month, AchievementBonusStatusEnum bonusStatus, List<Long> idCodes) {
        if (CollectionUtils.isEmpty(idCodes)) {
            return Collections.emptyList();
        }
        List<UserBonusResultDO> marketBonusResultDOList = achievementBonusDOCustomMapper.listMarketBonus(month,bonusStatus.getStatus(), idCodes);
        if (CollectionUtils.isEmpty(marketBonusResultDOList)) {
            return Collections.emptyList();
        }
        return marketBonusResultDOList.stream()
                .map(AchievementBonusConvert::convertMarketBonusResultDOToEntity)
                .collect(Collectors.toList());
    }

    @Override
    public void updateBonusStatus(Long idCode, Integer month, AchievementBonusStatusEnum curStatus, AchievementBonusStatusEnum targetStatus) {
        achievementBonusDOCustomMapper.updateBonusStatus(idCode,month,curStatus.getStatus(),targetStatus.getStatus());
    }

    @Override
    public List<Long> listBonusSettleUser(Integer month, Integer offset, Integer limit) {
        return achievementBonusDOCustomMapper.listBonusSettleUser(month,offset,limit);
    }

    @Override
    public List<AchievementBonus> listByIdCodesAndMonth(Integer month, List<Long> idCodeList) {
        if (month == null || CollectionUtils.isEmpty(idCodeList)) {
            return Collections.emptyList();
        }
        List<AchievementBonusDO> achievementBonusDOList = achievementBonusDOCustomMapper.listByIdCodesAndMonth(month,idCodeList);
        if (CollectionUtils.isEmpty(achievementBonusDOList)) {
            return Collections.emptyList();
        }
        return achievementBonusDOList.stream()
                .map(AchievementBonusConvert::convertToModel)
                .collect(Collectors.toList());

    }

    @Override
    public List<UserBonusResult> listAllMarketBonus(Integer month, AchievementBonusStatusEnum bonusStatus, List<Long> idCodes) {
        if (CollectionUtils.isEmpty(idCodes)) {
            return Collections.emptyList();
        }
        List<UserBonusResultDO> marketBonusResultDOList = achievementBonusDOCustomMapper.listAllMarketBonus(month,bonusStatus.getStatus(), idCodes);
        if (CollectionUtils.isEmpty(marketBonusResultDOList)) {
            return Collections.emptyList();
        }
        return marketBonusResultDOList.stream()
                .map(AchievementBonusConvert::convertMarketBonusResultDOToEntity)
                .collect(Collectors.toList());
    }



}
